package concurrency;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * Created by sunzhengjie on 2017/1/19.
 */
public class TestThreadCoordinate {

    static class Car {
        private boolean waxOn = false;//涂蜡

        public synchronized void waxed() {
            waxOn = true;
            notifyAll();
        }

        public synchronized void buffed() {
            waxOn = false;
            notifyAll();
        }

        public synchronized void waitForWaxing() throws InterruptedException {
            while (!waxOn) {
                wait();
            }
        }

        public synchronized void waitForBuffing() throws InterruptedException {
            while (waxOn) {
                wait();
            }
        }

        static class WaxOn implements Runnable {
            private Car car;

            public WaxOn(Car car) {
                this.car = car;
            }

            @Override
            public void run() {
                try {
                    while (!Thread.interrupted()) {
                        System.out.println("Wax on !");
                        TimeUnit.MICROSECONDS.sleep(200);
                        car.waxed();
                        car.waitForBuffing();
                    }
                } catch (InterruptedException e) {
                    System.out.println("Exiting via interrupt");
                }
                System.out.println("Ending Wax On task");
            }
        }

        static class WaxOff implements Runnable {
            private Car car;

            public WaxOff(Car car) {
                this.car = car;
            }

            @Override
            public void run() {
                try {
                    while (!Thread.interrupted()) {
                        car.waitForWaxing();
                        System.out.println("Wax Off !");
                        TimeUnit.MICROSECONDS.sleep(200);
                        car.buffed();
                    }
                } catch (InterruptedException e) {
                    System.out.println("Exiting via interrupt");
                }
                System.out.println("Ending Wax Off task");
            }
        }
    }

    public static class C {
        public void p1(){
            synchronized (this) {
                System.out.println("--a--");
                try {
                    TimeUnit.SECONDS.sleep(2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        public void p2() {
            synchronized (this){
                System.out.println("--b--");
                try {
                    TimeUnit.SECONDS.sleep(2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static class A implements Runnable {

        private C c;

        public A(C c) {
            this.c = c;
        }

        @Override
        public void run() {
            c.p1();
        }
    }

    public static class B implements Runnable {
        private C c;

        public B(C c) {
            this.c = c;
        }

        @Override
        public void run() {
            c.p2();
        }
    }

    public static class WaxOMatic {
        public static void main(String[] arhg) throws InterruptedException {
            C c = new C();
            ExecutorService exec = Executors.newCachedThreadPool();
            exec.execute(new A(c));
            exec.execute(new B(c));
            TimeUnit.SECONDS.sleep(5);
            exec.shutdownNow();
        }
    }
}
